<?php

namespace Trawind\Basics\Rules;

use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\DB;

class BatchExists implements Rule
{

    private $object;
    private $tabelObject;
    private $field;
    private $attribute;
    private $batchDatas;
    private $isSelected;
    private $indexList;
    /**
     * Create a new rule instance.
     *
     * Unique constructor.
     * @param $tabelObject
     */
    public function __construct($object, $tabelObject, $field = null)
    {
        $this->object = $object;
        $this->tabelObject = $tabelObject;
        $this->field = $field;
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        $data = explode(".", $attribute);
        $firstFiled = array_shift($data);
        $this->attribute = $attribute;
        $finalFiled = array_pop($data);
        if (is_numeric($firstFiled)) {
            $this->getIndexList($this->object->all(), $finalFiled);
        } else {
            $this->getIndexList($this->object->get($firstFiled), $finalFiled);
        }
        if (!$this->isSelected) {
            $selectField =  $this->field ? : $finalFiled;
            // get batch attribute
            $hasData = DB::table($this->tabelObject->getTable())
                ->select($selectField)
                ->whereIn($selectField, $this->indexList)
                ->get()
                ->toArray();
            $this->batchDatas = (array) array_column($hasData, $selectField, $selectField);
            $this->isSelected = true;
        }
        if (!isset($this->batchDatas[$value])) {
            return false;
        }
        return true;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return __('validation.exists', ['attribute' => $this->attribute]);
    }

    /**
     * @param $array
     * @param $index
     */
    private function getIndexList($array, $index) {
        if (!is_array($array)) {
            return ;
        }
        foreach ($array as $key => $item) {
            if (is_array($item)) {
                $this->getIndexList($item, $index);
            } else if ($key == $index) {
                $this->indexList[] = $item;
            }
        }
        return ;
    }
}
